# !/usr/bin/env python
# -*- coding=utf-8 -*-

import logging
from collections import defaultdict
import numpy as np
import random
import itertools


def log():
    logger = logging.getLogger('log')
    logger.setLevel(logging.DEBUG)
    fh = logging.FileHandler(r'C:\Users\新田草\Desktop\正仁量化\log\run.log')
    fh.setLevel(logging.DEBUG)
    formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
    fh.setFormatter(formatter)
    logger.addHandler(fh)
    return logger


LOG = log()


class EachTick(object):
    """
    基于交易逻辑的订单拆分方法
    tick 类，逐tick处理，并记录相应的中间状态
    """

    def __init__(self, row, pre_row, data_col_index):

        self.contract_multiplier = 5

        self.row = row
        self.pre_row = pre_row
        self.data_col_index = data_col_index

        self.temp_Date = self.row[self.data_col_index.Date_ind]
        self.temp_Time = self.row[self.data_col_index.Time_ind]
        self.temp_Timestamp = self.row[self.data_col_index.Timestamp_ind]

        self.temp_LastPx = self.row[data_col_index.LastPx_ind]
        self.temp_TickVolumeTrade = self.row[data_col_index.TickVolumeTrade_ind]
        self.temp_TickValueTrade = self.row[data_col_index.TickValueTrade_ind]

        # 计算订单方向；买方成交/卖方成交
        self.direction = None
        self.cal_direction()

        # 记录成交价/成交量/成交额
        self.split_trade_prices = list()
        self.split_trade_prices_dict = defaultdict(int)
        self.split_trade_values = list()
        self.split_trade_volumes = list()

        self.result = None  # list类型

    def cal_direction(self):
        """
        首先确定方向 direction
        :return:
        """
        if (self.temp_LastPx >= self.pre_row[self.data_col_index.AskPx1_ind] or
                (self.row[self.data_col_index.AskPx1_ind] > self.pre_row[self.data_col_index.AskPx1_ind]) or
                (self.row[self.data_col_index.AskPx1_ind] == self.pre_row[self.data_col_index.AskPx1_ind] and
                 self.row[self.data_col_index.AskVol1_ind] < self.pre_row[self.data_col_index.AskVol1_ind])):
            direction = "B"
        elif (self.temp_LastPx <= self.pre_row[self.data_col_index.BidPx1_ind] or
              (self.row[self.data_col_index.BidPx1_ind] < self.pre_row[self.data_col_index.BidPx1_ind]) or
              (self.row[self.data_col_index.BidPx1_ind] == self.pre_row[self.data_col_index.BidPx1_ind] and
               self.row[self.data_col_index.BidVol1_ind] < self.pre_row[self.data_col_index.BidVol1_ind])):
            direction = "S"
        # 买方前两档买量 大于 卖方前两档卖量 （买压 > 卖压）
        elif (np.sum(self.pre_row[self.data_col_index.BidVol1_ind: self.data_col_index.BidVol1_ind + 2]) >
              np.sum(self.pre_row[self.data_col_index.AskVol1_ind - 2: self.data_col_index.AskVol1_ind])):
            direction = "B"
        elif (np.sum(self.pre_row[self.data_col_index.BidVol1_ind: self.data_col_index.BidVol1_ind + 2]) <
              np.sum(self.pre_row[self.data_col_index.AskVol1_ind - 2: self.data_col_index.AskVol1_ind])):
            direction = "S"
        else:
            if random.random() > 0.5:
                direction = "B"
            else:
                direction = "S"
        self.direction = direction

    def split_order(self):
        """
        考虑 1手、2手、4手以及(3手和>=5手多手)的情况
        :return:
        """
        # 将tick数据进行拆分，变为逐笔数据
        if self.temp_TickVolumeTrade == 1:
            self.split_trade_prices.append(self.temp_LastPx)
            self.split_trade_values.append(self.temp_LastPx*1*self.contract_multiplier)
            self.split_trade_volumes.append(1)

        if self.temp_TickVolumeTrade == 2:
            self.split2trades()

        if self.temp_TickVolumeTrade == 4:
            self.split4trades()

        if 20 >= self.temp_TickVolumeTrade >= 5 or self.temp_TickVolumeTrade == 3:
            """
            当成交量在 5手 => 10手的时候，可用此函数进行拆分(超过12手，会报错”MemoryError“)
            大于 12 手及以上，计算量较大，则需要另外定制
            """
            self.splitMultitrades()

        try:
            if self.temp_TickVolumeTrade >= 2:
                # 合并价格相同的单子
                self.merge_trades(self.temp_TickVolumeTrade)
        except Exception as e:
            """
            debug 使用
            """
            print("合并成交数据出错(in merge_trades):", e)
            print(self.row)
            print(self.pre_row)
            print(self.split_trade_prices)
            print(self.split_trade_values)
            print(self.split_trade_volumes)
            print(self.direction)
            exit(2)

    def merge_trades(self):
        """
        合并成交价格相同的成交单
        :return:
        """
        price_ls = list()
        volume_ls = list()
        value_ls = list()

        self.split_trade_prices = np.array(self.split_trade_prices)
        self.split_trade_values = np.array(self.split_trade_values)
        self.split_trade_volumes = np.array(self.split_trade_volumes)
        # 合并成交价相同的交易
        for ind, each in enumerate(self.split_trade_prices):
            self.split_trade_prices_dict[each] += self.split_trade_volumes[ind]
        for each in self.split_trade_prices_dict.items():
            # 该成交价格下，交易量大于1
            if each[1] >= 2:
                price_ls.append(each[0])
                volume_ls.append(np.sum(self.split_trade_volumes[self.split_trade_prices == each[0]]))
                value_ls.append(np.sum(self.split_trade_values[self.split_trade_prices == each[0]]))
            # 该成交价格下，交易量等于1
            else:
                price_ls.append(each[0])
                volume_ls.append(1)
                value_ls.append(each[0]*1*5)
        self.split_trade_prices = price_ls
        self.split_trade_volumes = volume_ls
        self.split_trade_values = value_ls

    def output(self):
        results = list()
        for price, volume, value in zip(self.split_trade_prices,
                                        self.split_trade_volumes, self.split_trade_values):
            result = [self.row[self.data_col_index.Date_ind],
                      self.row[self.data_col_index.Time_ind],
                      self.row[self.data_col_index.Timestamp_ind],
                      price,
                      volume,
                      value,
                      self.direction
                      ]
            results.append(result)
        self.result = results

    def split2trades(self):
        self.split_trade_prices.append(self.temp_LastPx)
        temp_value = self.temp_LastPx * 1 * 5
        self.split_trade_values.append(temp_value)
        self.temp_TickValueTrade -= temp_value
        self.split_trade_values.append(self.temp_TickValueTrade)
        self.split_trade_prices.append(self.temp_TickValueTrade * 0.2)
        self.split_trade_volumes.extend([1, 1])

    def split4trades(self):
        """
        成交四笔的情形，大部分 AskVolume1=2或者BidVolume1=2
        """
        # 特殊情形(需要根据合约定制)，可加速计算，AskVolume1=2或者BidVolume1=2
        if (self.pre_row[self.data_col_index.AskVol1_ind] == 2 or
                self.pre_row[self.data_col_index.BidVol1_ind] == 2):
            self.split_trade_prices.extend([self.temp_LastPx, self.temp_LastPx])
            temp_value = self.temp_LastPx * 1 * 5
            self.split_trade_values.extend([temp_value, temp_value])
            self.temp_TickValueTrade -= (temp_value * 2)
            # 如果可以整除，则简化，直接用中间价作为成交价估计
            # 当然此处可加入与 order_book 量价变化进行轮询、对比、运算，更准确地确定成交价
            if self.temp_TickValueTrade % 10 == 0:
                temp_price = self.temp_TickValueTrade * 0.1
                temp_value = temp_price * 1 * 5
                self.split_trade_prices.extend([temp_price, temp_price])
                self.split_trade_values.extend([temp_value, temp_value])
            else:
                middle_price = self.temp_TickValueTrade * 0.1
                while middle_price % 5 != 0.0:
                    middle_price += 2.5  # 2.5 由 contract_multiplier 决定
                self.split_trade_prices.extend([middle_price, self.temp_TickValueTrade * 0.2 - middle_price])
                self.split_trade_values.extend([middle_price * 5, self.temp_TickValueTrade - middle_price * 5])
        # 一般性通用情况
        else:
            # 成交的4手中切片数据的最后一手(最新一手)
            self.split_trade_prices.append(self.temp_LastPx)
            temp_value = self.temp_LastPx * 1 * 5
            self.split_trade_values.append(temp_value)
            self.temp_TickValueTrade -= temp_value

            temp_BidPx1 = self.pre_row[self.data_col_index.BidPx1_ind]
            temp_BidPx2 = self.pre_row[self.data_col_index.BidPx1_ind + 1]
            temp_AskPx1 = self.pre_row[self.data_col_index.AskPx1_ind]
            temp_AskPx2 = self.pre_row[self.data_col_index.AskPx1_ind - 1]

            # 还剩下三个成交单
            # 该价格组合部分可以参考背包问题中动态规划思想
            if self.direction == "S":
                # 列出所有可能价格，进行排列组合，找出距离 LastPrice 最近的 三个价格
                # 如果买一卖一、买一买二距离过大，则缩小，以便下一步排列组合减少搜索复杂度
                if temp_AskPx1 - temp_BidPx1 > 100:
                    temp_AskPx1 = temp_BidPx1 + 100
                if temp_BidPx1 - temp_BidPx2 > 100:
                    temp_BidPx2 = temp_BidPx1 - 100
                # 生成重复的排列组合，(itertools.combinations: 不可重复)
                # [23000, 23200, 5]
                price_list = list(
                    itertools.product(list(range(int(temp_BidPx2), int(temp_AskPx1), 5)),
                                      repeat=3))
                price_array = np.array(price_list)
                # 把组合价值不正确的剔除
                price_array = price_array[(price_array * 5).sum(axis=1) == self.temp_TickValueTrade]

                temp_min = np.inf
                temp_price = list()
                for each in price_array:
                    temp = np.sum(np.square((each - self.temp_LastPx)))
                    if temp < temp_min:
                        temp_min = temp
                        temp_price = each
                self.split_trade_prices.extend(temp_price)
                for price in self.split_trade_prices[1:]:
                    self.split_trade_values.append(price * 1 * 5)
            if self.direction == "B":
                # 列出所有可能价格，进行排列组合，找出距离 LastPrice 最近的 三个价格
                # 如果卖一卖二、卖一买一距离过大，则缩小，以便下一步排列组合减少搜索复杂度
                if temp_AskPx2 - temp_AskPx1 > 100:
                    temp_AskPx2 = temp_AskPx1 + 100
                if temp_AskPx1 - temp_BidPx1 > 100:
                    temp_BidPx1 = temp_AskPx1 - 100
                # 生成重复的排列组合，(itertools.combinations: 不可重复)
                price_list = list(
                    itertools.product(list(range(int(temp_BidPx1), int(temp_AskPx2), 5)),
                                      repeat=3))
                price_array = np.array(price_list)
                # 把组合总价值不正确的剔除
                price_array = price_array[(price_array * 5).sum(axis=1) == self.temp_TickValueTrade]

                temp_min = np.inf
                temp_price = list()
                # 用离差平方和，计算与“中间价”的距离
                for each in price_array:
                    temp = np.sum(np.square((each - self.temp_LastPx)))
                    if temp < temp_min:
                        temp_min = temp
                        temp_price = each
                self.split_trade_prices.extend(temp_price)
                for price in self.split_trade_prices[1:]:
                    self.split_trade_values.append(price * 1 * 5)

        self.split_trade_volumes.extend([1] * 4)

    def splitMultitrades(self):
        """
        改进：可先检查pre_row与row中 AskVol1 和 BidVol1 变动情况，
        看其是否有大单(比如两手/三手/四手)可直接成交，以减少后续排列组合复杂度
        :return:
        """
        # 如果前一个 tick 的一档量较大(>=2)，
        # 且下一个tick的一档价格上移/下移(下个tick一档价等于上个tick二挡或者三挡)，
        # 则大概率默认前一个 tick 一档全部被吃掉(也存在未吃完一档量的情况，多写个elif即可)
        temp_volume = 0
        temp_price = 0

        # 先处理前 temp_volume 笔交易
        if (self.direction == "B" and (self.temp_TickVolumeTrade > self.pre_row[self.data_col_index.AskVol1_ind] >= 2) and
            (self.row[self.data_col_index.AskPx1_ind] ==
                self.pre_row[self.data_col_index.AskPx1_ind-1] or
                self.row[self.data_col_index.AskPx1_ind] ==
                self.pre_row[self.data_col_index.AskPx1_ind-2])) or \
                (self.direction == "S" and (self.temp_TickVolumeTrade > self.pre_row[self.data_col_index.BidVol1_ind] >= 2) and
                 (self.row[self.data_col_index.BidPx1_ind] == self.pre_row[self.data_col_index.BidPx1_ind+1] or
                 self.row[self.data_col_index.BidPx1_ind] == self.pre_row[self.data_col_index.BidPx1_ind+2])):
            if self.direction == "B":
                temp_volume = int(self.pre_row[self.data_col_index.AskVol1_ind])
                temp_price = self.pre_row[self.data_col_index.AskPx1_ind]
            if self.direction == "S":
                temp_volume = int(self.pre_row[self.data_col_index.BidVol1_ind])
                temp_price = self.pre_row[self.data_col_index.BidPx1_ind]

            self.split_trade_volumes.append(int(temp_volume))
            self.split_trade_prices.append(int(temp_price))
            temp_value = temp_price * temp_volume * self.contract_multiplier
            self.split_trade_values.append(temp_value)
            self.temp_TickValueTrade -= temp_value

        elif (self.direction == "B" and self.temp_LastPx == self.pre_row[self.data_col_index.AskPx1_ind] and
        self.pre_row[self.data_col_index.AskVol1_ind] >= self.temp_TickVolumeTrade) or (self.direction == "S" and
        (self.temp_LastPx == self.pre_row[self.data_col_index.BidPx1_ind] and
         self.pre_row[self.data_col_index.BidVol1_ind] >= self.temp_TickVolumeTrade)):
            # 一档订单没吃完，全在一档位置成交
            self.split_trade_prices.append(self.temp_LastPx)
            self.split_trade_volumes.append(self.temp_TickVolumeTrade)
            self.split_trade_values.append(int(self.temp_LastPx * self.temp_TickVolumeTrade * self.contract_multiplier))
            logging.info("订单在一档位置全部成交，跳过数据组合操作，减少时间复杂度")
            logging.info("temp_TickVolumeTrade: %s" % self.temp_TickVolumeTrade)
            if self.direction == "B":
                logging.info("pre_row_AskVol1: %s" % self.pre_row[self.data_col_index.AskVol1_ind])
            elif self.direction == "S":
                logging.info("pre_row_BidVol1 %s " % self.pre_row[self.data_col_index.BidVol1_ind])
            return  # 无需下一步计算，直接返回即可, 减小计算复杂度

        else:
            # 否则，按最常规的，有一个订单一定是按 LastPx 成交
            temp_volume = 1
            self.split_trade_volumes.append(temp_volume)
            self.split_trade_prices.append(self.temp_LastPx)
            temp_value = self.temp_LastPx * temp_volume * 5
            self.split_trade_values.append(temp_value)
            self.temp_TickValueTrade -= temp_value

        # 然后计算剩下的 (self.temp_TickVolumeTrade-temp_volume) 手
        # 可能存在 BidPx2/AskPx2 两个报价不存在的情形,代码鲁棒性起见，只取一档
        temp_BidPx1 = self.pre_row[self.data_col_index.BidPx1_ind]
        temp_AskPx1 = self.pre_row[self.data_col_index.AskPx1_ind]

        logging.info("当前tick有 %s 手单子" % self.temp_TickVolumeTrade)
        logging.info("已预处理 %s 手单子" % temp_volume)
        # logging.info("direction: %s " % self.direction)
        if self.direction == "S":
            # 列出所有可能价格，进行排列组合，找出距离 LastPrice 最近的 三个价格

            price_ceil = temp_AskPx1
            price_ground = temp_BidPx1 - 100
            logging.info("price_ceil=%s" % price_ceil)
            logging.info("price_ground=%s" % price_ground)

            # 27个数值中选: 6个、10个、11个，排列组合个数分别为：30万，840万，1300万，
            # 所以当 temp_TickVolumeTrade=12时，容易MemoryError
            # 先无重复组合：combinations
            price_list = list(
                itertools.combinations(range(int(price_ground), int(price_ceil), self.contract_multiplier),
                                  int(self.temp_TickVolumeTrade-temp_volume)))
            # 然后在temp_price 附近，增加可重复组合
            price_list.extend(itertools.product(range(int(temp_price-30), int(temp_price+30), self.contract_multiplier),
                                                repeat=int(self.temp_TickVolumeTrade-temp_volume)))
            logging.info("开始，排列组合数共 %s 个情形." % (len(price_list)))
            # 用set剔除重复的排列组合
            price_array = np.array(list(set(price_list)))
            # 把组合价值不正确的剔除
            price_array = price_array[(price_array * self.contract_multiplier).sum(axis=1) == self.temp_TickValueTrade]
            logging.info("剔除后，排列组合数共 %s 个情形." % (len(price_array)))
            temp_min = np.inf
            temp_price_ls = list()
            for each in price_array:
                temp = np.sum(np.square((each - temp_BidPx1)))
                if temp < temp_min:
                    temp_min = temp
                    temp_price_ls = each
            # 更新成交价格和交易额
            self.split_trade_prices.extend(temp_price_ls)
            for price in self.split_trade_prices[1:]:
                self.split_trade_values.append(price * 1 * self.contract_multiplier)
                self.split_trade_volumes.append(1)

        if self.direction == "B":
            # 列出所有可能价格，进行排列组合，找出距离 LastPrice 最近的价格
            price_ceil = temp_AskPx1 + 100
            price_ground = temp_BidPx1
            price_list = list(
                itertools.combinations(range(int(price_ground), int(price_ceil), self.contract_multiplier),
                                       int(self.temp_TickVolumeTrade-temp_volume)))
            price_list.extend(
                [([each] * int(self.temp_TickVolumeTrade-temp_volume)) for each in range(int(price_ground), int(price_ceil), self.contract_multiplier)])
            price_array = np.array(price_list)
            # 把组合总价值不正确的剔除
            price_array = price_array[(price_array * self.contract_multiplier).sum(axis=1) == self.temp_TickValueTrade]
            temp_min = np.inf
            temp_price_ls = list()
            # 用离差平方和，计算与“中间价”的距离
            for each in price_array:
                temp = np.sum(np.square((each - temp_BidPx1)))
                if temp < temp_min:
                    temp_min = temp
                    temp_price_ls = each
            # 更新成交价格和交易额
            self.split_trade_prices.extend(temp_price_ls)
            # 注意是 (self.temp_TickVolumeTrade-1) 手，第一手已经更新进去
            for price in self.split_trade_prices[1:]:
                self.split_trade_values.append(price * 1 * self.contract_multiplier)
                self.split_trade_volumes.append(1)


class DynamicProgrammingSolution(object):
    """
    基于动态规划的订单拆分方法
    """

    def __init__(self, tick_data, pre_row, data_col_ind):

        self.row = tick_data
        self.pre_row = pre_row
        self.data_col_ind = data_col_ind

        self.last_price = self.row[self.data_col_ind.LastPx_ind]

        self.avg_price = round(self.row[self.data_col_ind.TickValueTrade_ind] / \
                    self.row[self.data_col_ind.TickVolumeTrade_ind] / 200, 1)

        self.tickTradeValue = self.row[self.data_col_ind.TickValueTrade_ind]
        self.tickTradeVolume = self.row[self.data_col_ind.TickVolumeTrade_ind]

        self.benchmark = None

        self.direction = None
        self.calculate_direction()

        self.contract_multiplier = 200
        self.contract_tick = 0.2

        # 记录成交价/成交量/成交额
        self.split_trade_prices = list()
        self.split_trade_prices_dict = defaultdict(int)
        self.split_trade_values = list()
        self.split_trade_volumes = list()

        self.result = None  # list类型

    def calculate_direction(self):

        if self.last_price > self.avg_price:
            self.direction = "B"
        elif self.last_price < self.avg_price:
            self.direction = "S"
        else:
            direction = None
            if (self.last_price >= self.pre_row[self.data_col_ind.AskPx1_ind] or
                    (self.row[self.data_col_ind.AskPx1_ind] > self.pre_row[self.data_col_ind.AskPx1_ind]) or
                    (self.row[self.data_col_ind.AskPx1_ind] == self.pre_row[self.data_col_ind.AskPx1_ind] and
                     self.row[self.data_col_ind.AskVol1_ind] < self.pre_row[self.data_col_ind.AskVol1_ind])):
                direction = "B"
            elif (self.last_price <= self.pre_row[self.data_col_ind.BidPx1_ind] or
                  (self.row[self.data_col_ind.BidPx1_ind] < self.pre_row[self.data_col_ind.BidPx1_ind]) or
                  (self.row[self.data_col_ind.BidPx1_ind] == self.pre_row[self.data_col_ind.BidPx1_ind] and
                   self.row[self.data_col_ind.BidVol1_ind] < self.pre_row[self.data_col_ind.BidVol1_ind])):
                direction = "S"
            # 买方前两档买量 大于 卖方前两档卖量 （买压 > 卖压）
            elif (np.sum(self.pre_row[self.data_col_ind.BidVol1_ind: self.data_col_ind.BidVol1_ind + 2]) >
                  np.sum(self.pre_row[self.data_col_ind.AskVol1_ind - 2: self.data_col_ind.AskVol1_ind])):
                direction = "B"
            elif (np.sum(self.pre_row[self.data_col_ind.BidVol1_ind: self.data_col_ind.BidVol1_ind + 2]) <
                  np.sum(self.pre_row[self.data_col_ind.AskVol1_ind - 2: self.data_col_ind.AskVol1_ind])):
                direction = "S"
            else:
                if random.random() > 0.5:
                    direction = "B"
                else:
                    direction = "S"
            self.direction = direction

    def split_trades(self):

        if self.tickTradeVolume == 1:
            self.split_trade_prices.append(self.last_price)
            self.split_trade_values.append(self.last_price*self.tickTradeVolume*self.contract_multiplier)
            self.split_trade_volumes.append(1)

        elif self.tickTradeVolume == 2:
            self.split_trade_prices.append(self.last_price)
            temp_value = self.last_price * 1 * self.contract_multiplier
            self.split_trade_values.append(temp_value)
            self.tickTradeValue -= temp_value
            self.split_trade_values.append(self.tickTradeValue)
            self.split_trade_prices.append(self.tickTradeValue / self.contract_multiplier)
            self.split_trade_volumes.extend([1, 1])

        if self.tickTradeVolume > 2:
            total_prices = None
            temp_avg_price = self.avg_price
            if self.last_price == self.avg_price:
                self.split_trade_prices.append(self.last_price)
                self.split_trade_values.append(self.tickTradeValue)
                self.split_trade_volumes.append(self.tickTradeVolume)
                return

            if self.last_price > self.avg_price:
                while int(str(round(temp_avg_price, 1)).split(".")[-1]) % 2 != 0:
                    temp_avg_price -= 0.1
                ground = round(round(temp_avg_price, 1) - self.contract_tick * 50, 1)

                self.benchmark = ground
                ceil = self.last_price - ground
                total_prices = np.arange(self.contract_tick, ceil, self.contract_tick)
                total_prices = [round(i, 1) for i in total_prices]
                total_prices.append(round(ceil, 1))
                total_prices = np.array(list(set(total_prices)))
                total_prices.sort()

            if self.last_price < self.avg_price:
                while int(str(temp_avg_price).split(".")[-1]) % 2 != 0:
                    temp_avg_price = round(temp_avg_price+0.1, 1)

                ceil = round(temp_avg_price + self.contract_tick * 50 - self.last_price, 1)
                self.benchmark = self.last_price
                total_prices = np.arange(self.contract_tick, ceil, self.contract_tick)
                total_prices = [round(i, 1) for i in total_prices]
                total_prices = np.array(total_prices)
                total_prices.sort()

            price_num = np.zeros(len(total_prices))

            temp_value = round(self.tickTradeValue / self.contract_multiplier - self.benchmark * self.tickTradeVolume, 1)
            LOG.info("temp_value = %s" % temp_value)

            all_values = list(np.arange(self.contract_tick, temp_value, self.contract_tick))
            all_values.append(temp_value)
            all_values = [round(i, 1) for i in all_values]
            all_values = np.array(list(set(all_values)))
            all_values.sort()

            LOG.info("all_values = %s" % all_values)
            LOG.info("len(all_values) = %s" % len(all_values))
            LOG.info("total_prices = %s" % total_prices)
            LOG.info("len(total_prices) = %s" % len(total_prices))

            money_min = np.zeros(int(round(temp_value / self.contract_tick))+1)
            records_min = np.zeros(int(round(temp_value / self.contract_tick))+1)

            # 算法核心部分
            ind_temp_min = None
            ind_temp = None
            for ind, i in enumerate(all_values):

                min_num = temp_value / self.contract_tick
                ind += 1
                for j in range(len(total_prices)):
                    if total_prices[j] <= i and min_num > money_min[int(round((i - total_prices[j]) / self.contract_tick, 1))]:
                        min_num = money_min[int(round((i - total_prices[j]) / self.contract_tick, 1))]
                        ind_temp_min = j
                money_min[ind] = round(min_num) + 1
                records_min[ind] = total_prices[round(ind_temp_min)]
            while temp_value > 0:
                ind = int(round(temp_value / self.contract_tick, 1))
                for j in range(len(total_prices)):
                    if records_min[ind] == total_prices[j]:
                        price_num[j] += 1
                        ind_temp = j
                temp_value -= total_prices[ind_temp]
                temp_value = round(temp_value, 1)

            LOG.info("money_min = %s" % money_min)
            LOG.info("records_min = %s" % records_min)

            for ind, num in enumerate(price_num):
                if num != 0:
                    self.split_trade_prices.append(total_prices[ind] + self.benchmark)
                    self.split_trade_volumes.append(num)
                    self.split_trade_values.append((total_prices[ind] + self.benchmark) *
                                                   num * self.contract_multiplier)
            # 浮点数处理
            self.split_trade_prices = [round(i, 1) for i in self.split_trade_prices]
            self.split_trade_values = [round(i, 1) for i in self.split_trade_values]
            self.split_trade_volumes = [round(i, 1) for i in self.split_trade_volumes]

            splited_order = sum(self.split_trade_volumes)
            if splited_order != self.tickTradeVolume:
                LOG.info("此单子拆分手数与原单子不同: %s" % self.row[self.data_col_ind.Timestamp_ind])
                LOG.info("原手数：%s | 拆分手数：%s" % (self.tickTradeVolume, splited_order))
                LOG.info("self.split_trade_prices = %s" % self.split_trade_prices)
                LOG.info("self.split_trade_volumes = %s" % self.split_trade_volumes)
            else:
                LOG.info("此单子拆分笔数与原单子相同: %s" % self.row[self.data_col_ind.Timestamp_ind])
                LOG.info("原笔数：%s | 拆分笔数：%s" % (self.tickTradeVolume, splited_order))
                LOG.info("self.split_trade_prices = %s" % self.split_trade_prices)
                LOG.info("self.split_trade_volumes = %s" % self.split_trade_volumes)
            LOG.info("=" * 100)
        self.merge_trades()

    def output(self):

        results = list()
        for price, volume, value in zip(self.split_trade_prices,
                                        self.split_trade_volumes, self.split_trade_values):
            result = [self.row[self.data_col_ind.Date_ind],
                      self.row[self.data_col_ind.Time_ind],
                      self.row[self.data_col_ind.Timestamp_ind],
                      price,
                      volume,
                      value,
                      self.direction
                      ]
            results.append(result)
        self.result = results

    def merge_trades(self):
        """
        合并成交价格相同的成交单
        :return:
        """
        price_ls = list()
        volume_ls = list()
        value_ls = list()

        self.split_trade_prices = np.array(self.split_trade_prices)
        self.split_trade_values = np.array(self.split_trade_values)
        self.split_trade_volumes = np.array(self.split_trade_volumes)
        # 合并成交价相同的交易
        for ind, each in enumerate(self.split_trade_prices):
            self.split_trade_prices_dict[each] += self.split_trade_volumes[ind]
        for each in self.split_trade_prices_dict.items():
            # 该成交价格下，交易量大于1
            if each[1] >= 2:
                price_ls.append(each[0])
                volume_ls.append(np.sum(self.split_trade_volumes[self.split_trade_prices == each[0]]))
                value_ls.append(np.sum(self.split_trade_values[self.split_trade_prices == each[0]]))
            # 该成交价格下，交易量等于1
            else:
                price_ls.append(each[0])
                volume_ls.append(1)
                value_ls.append(each[0]*1*5)
        self.split_trade_prices = price_ls
        self.split_trade_volumes = volume_ls
        self.split_trade_values = value_ls

